package com.hitqz.robot.util;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Maps;
import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map;

/**
 * @author xupkun
 * @date 2024/11/3
 */
@Slf4j
public class PlcToolKit {

    private static Map<String, ModbusMaster> master = Maps.newHashMap();


    public static void sendHeartBeat() {
        for (String key : master.keySet()) {
            try {
                ModbusMaster modbusMaster = master.get(key);
                if (!modbusMaster.isConnected()) {
                    modbusMaster.connect();
                }
                modbusMaster.writeSingleRegister(1, 0, 1);
            }catch (Exception e) {
                //log.info("Error sending heartbeat {} ----- {} ", key , e.getMessage());
            }

        }

    }

    public static void login(String ip, Integer port) {
        try {
            TcpParameters tcpParameters = new TcpParameters();
            InetAddress adress = InetAddress.getByName(ip);
            tcpParameters.setHost(adress);
            tcpParameters.setPort(port);
            tcpParameters.setKeepAlive(true);
            ModbusMaster modbusMaster = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);
            master.put(ip, modbusMaster);
            log.info("plc 连接成功:" + ip);
        } catch (UnknownHostException e) {
            log.error("PLC通讯连接失败，Modbus通讯【" +
                    DateUtil.format(new Date(), "yyyy-MM-dd HH:mm") + "] 请及时排查。错误：" + e.getMessage());
        }

    }


    /**
     * 写入寄存器数据
     * @param startAddress
     * @param value
     * @return
     */
    public static int writeRegister(String ip, Integer port, Integer startAddress, Integer value) {
        try {
            ModbusMaster modbusMaster = master.get(ip);
            if (modbusMaster == null) {
                PlcToolKit.login(ip, port);
                modbusMaster = master.get(ip);
            }
            modbusMaster.writeSingleRegister(1, startAddress, value);
            return 1;
        } catch (Exception e) {
            log.error("PLC通讯写寄存器失败，Modbus通讯【" +
                    DateUtil.format(new Date(), "yyyy-MM-dd HH:mm") + "】写入寄存器【" + startAddress + "】地址写【" + value + "】操作失败，请及时排查。错误：" + e.getMessage());
            return 0;
        } finally {
        }
    }



    /**
     * 读寄存器数据
     *
     * @param
     * @param
     * @param
     */
    public static Integer readSingleRegister(String ip, int port, Integer startAddress) {
        try {
            ModbusMaster modbusMaster = master.get(ip);
            if (modbusMaster == null) {
                PlcToolKit.login(ip, port);
                modbusMaster = master.get(ip);
            }
            if (!modbusMaster.isConnected()) {
                modbusMaster.connect();
            }
            int[] data = modbusMaster.readHoldingRegisters(1, startAddress, 1);
            return data[0];
        } catch (Exception e) {
            log.error("PLC通讯读寄存器失败，Modbus通讯【" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm") + "】读取寄存器【" + startAddress + "】数据操作失败，请及时排查。错误：" + e.getMessage());
            return -1;
        } finally {
        }
    }

    @PreDestroy
    public void destroy() throws ModbusIOException {
        for (String key : master.keySet()) {
            log.info("plc destroyed" + key);
            ModbusMaster modbusMaster = master.get(key);
            if (modbusMaster != null && modbusMaster.isConnected()) {
                modbusMaster.disconnect();
            }
        }
    }


}
